package com.snap.update.update;


import android.os.Bundle;
import android.util.Log;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

public class UpdateTask2 implements Callable<UpdateRes> {

    private static final String TAG = "UpdateTask";

    private static final int fragmentSize = 512;

    private final UpdateSerialPortHelper serialPortHelper;
    private final int moduleIndex;
    private final byte[] data;
    private final String version;

    private int cur;
    private int total;
    private OnUpdateListener listener;

    public UpdateTask2(UpdateSerialPortHelper serialPortHelper, int moduleIndex,
                       byte[] data, String version) {
        this.serialPortHelper = serialPortHelper;
        this.moduleIndex = moduleIndex;
        this.data = data;
        this.version = version;
    }

    @Override
    public UpdateRes call() throws Exception {
        Bundle bundle;
        byte[] res;
        int state = getState();
        if (state == -1) state = getState();
        if (state == -1) {
            return new UpdateRes("获取状态失败1");
        } else if (state == 0) {
            //初始化
            bundle = serialPortHelper.execute(UpdateCmd.init(moduleIndex));
            if (!bundle.getBoolean("suc")) {
                return new UpdateRes("初始化通信失败");
            } else {
                res = bundle.getByteArray("data");
                if (res == null || res[6] != 0) return new UpdateRes("初始化失败");
            }
            TimeUnit.MILLISECONDS.sleep(1000);
        } else if (state == 1 || state == 2) {
            //记录此类异常信息？？
        }

        //配置
        String[] arr = version.split("\\.");
        bundle = serialPortHelper.execute(UpdateCmd.config(moduleIndex, data.length, fragmentSize,
                Integer.parseInt(arr[0]), Integer.parseInt(arr[1]), Integer.parseInt(arr[2])));
        if (!bundle.getBoolean("suc")) return new UpdateRes("配置帧通讯失败");
        res = bundle.getByteArray("data");
        if (res == null || res[6] != 0)
            return new UpdateRes("配置帧失败：" + (res != null ? res[6] : "null"));

        //数据
        int endSize = data.length % fragmentSize;
        int fragments = data.length / fragmentSize + (endSize > 0 ? 1 : 0);
        for (int i = 0; i < fragments; i++) {
            if (listener != null) {
                listener.onAnalyzeProcess(cur, total, i * 1d / fragments);
            }
            int size;
            if (endSize == 0) {
                size = fragmentSize;
            } else {
                size = i == fragments - 1 ? endSize : fragmentSize;
            }
            bundle = serialPortHelper.execute(UpdateCmd.data(moduleIndex, i + 1, data, i * fragmentSize, size));
            if (!bundle.getBoolean("suc")) return new UpdateRes("数据帧第" + i + "个通讯失败");
            res = bundle.getByteArray("data");
            if (res == null || res[7] != 0)
                return new UpdateRes("数据帧第" + i + "个失败：" + (res != null ? res[7] : "null"));
            int doneIndex = res[6] & 0xff;
            Log.e(TAG, "最后确认帧编号 " + doneIndex);
            if (doneIndex != i + 1) return new UpdateRes("数据帧第" + i + "个未能正确接收");
        }
        TimeUnit.MILLISECONDS.sleep(1000);
        state = getState();
        if (state == -1) state = getState();
        if (state == -1) {
            return new UpdateRes("获取状态失败2");
        } else if (state == 5) {
            bundle = serialPortHelper.execute(UpdateCmd.jump(moduleIndex));
            if (!bundle.getBoolean("suc")) return new UpdateRes("跳转用户程序失败");
            else return UpdateRes.sucRes();
        } else if (state == 0xee) {
            return new UpdateRes("数据帧传输失败");
        } else {
            return new UpdateRes("bl程序状态错误!5");
        }
    }

    private int getState() throws InterruptedException {
        Bundle bundle = serialPortHelper.execute(UpdateCmd.getStatus(moduleIndex));
        if (!bundle.getBoolean("suc")) return -1;
        byte[] res = bundle.getByteArray("data");
        if (res == null || res.length < 7) return -1;
        return res[6];
    }

    public void setListener(int i, int size, OnUpdateListener listener) {
        this.cur = i;
        this.total = size;
        this.listener = listener;
    }
}